package day28.ThreadTest;

/**
 * 线程同步演示类
 * 展示多种线程同步方式：同步方法、同步代码块、静态同步方法
 * 比较了不同同步方式的使用场景
 * 演示了多线程对共享资源的操作
 * 
 * 涉及知识点：
 * 1. Java多线程基础
 * 2. synchronized关键字的使用
 * 3. 线程同步机制
 * 4. 线程间通信
 * 5. 静态方法与实例方法的同步区别
 * 6. 锁对象的概念
 */
public class SynchronizationDemo {
    public static void main(String[] args) {
        // 创建共享对象
        Counter counter = new Counter();
        
        // 创建并启动多个线程
        // 涉及知识点：Thread类的使用，多线程创建方式
        Thread t1 = new Thread(new CounterTask(counter, "Thread-1"), "Thread-1");
        Thread t2 = new Thread(new CounterTask(counter, "Thread-2"), "Thread-2");
        Thread t3 = new Thread(new CounterTask(counter, "Thread-3"), "Thread-3");
        
        t1.start();
        t2.start();
        t3.start();
        
        // 等待所有线程完成
        // 涉及知识点：线程join()方法，线程等待机制
        try {
            t1.join();
            t2.join();
            t3.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("Final count: " + Counter.getStaticCount());
    }
}

/**
 * 计数器类，演示多种同步方式
 * 
 * 涉及知识点：
 * 1. Java类的设计
 * 2. 实例变量与静态变量的区别
 * 3. synchronized关键字的不同使用方式
 * 4. 锁机制的实现原理
 */
class Counter {
    private int count = 0;  // 实例变量，每个实例独有
    private static int staticCount = 0;  // 静态变量，所有实例共享
    private final Object lock = new Object(); // 用于同步代码块的锁对象
    
    /**
     * 同步方法示例 - 实例方法同步
     * 
     * 涉及知识点：
     * 1. synchronized修饰实例方法：锁是当前实例对象(this)
     * 2. 同一实例的同步方法同一时间只能被一个线程访问
     * 3. 不同实例的同步方法可以同时执行
     * 4. 原子性保证：方法内的操作具有原子性
     */
    public synchronized void incrementSyncMethod() {
        count++;
        staticCount++;
        System.out.println(Thread.currentThread().getName() + " - Count: " + count + 
                          ", StaticCount: " + staticCount);
        
        // 模拟一些处理时间
        // 涉及知识点：线程sleep()方法，线程状态转换
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            // 涉及知识点：线程中断处理，InterruptedException处理
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * 同步代码块示例
     * 
     * 涉及知识点：
     * 1. synchronized代码块：可以指定任意对象作为锁
     * 2. 锁的粒度控制：相比同步方法更精细
     * 3. 锁对象的选择：可以是this、类对象、自定义对象等
     * 4. 性能优化：只对需要同步的代码加锁
     */
    public void incrementSyncBlock() {
        // 使用自定义对象作为锁
        synchronized(lock) {
            count++;
            staticCount++;
            System.out.println(Thread.currentThread().getName() + " - Count: " + count + 
                              ", StaticCount: " + staticCount);
        }
        
        // 模拟一些处理时间
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * 静态同步方法示例
     * 
     * 涉及知识点：
     * 1. synchronized修饰静态方法：锁是当前类的Class对象
     * 2. 类锁与实例锁的区别：静态方法使用类锁，实例方法使用实例锁
     * 3. 静态方法同步：所有线程对同一类的静态同步方法的访问是互斥的
     * 4. 锁的范围：类锁影响所有实例
     */
    public static synchronized void incrementStaticSyncMethod() {
        staticCount++;
        System.out.println(Thread.currentThread().getName() + " - StaticCount: " + staticCount);
        
        // 模拟一些处理时间
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * 获取静态计数器值
     * @return 静态计数器值
     * 
     * 涉及知识点：
     * 1. 静态方法的定义和使用
     * 2. getter方法的设计原则
     * 3. 静态变量的访问方式
     */
    public static int getStaticCount() {
        return staticCount;
    }
    
    /**
     * 获取实例计数器值
     * @return 实例计数器值
     * 
     * 涉及知识点：
     * 1. 实例方法的定义和使用
     * 2. getter方法的设计原则
     * 3. 实例变量的访问方式
     */
    public int getCount() {
        return count;
    }
}

/**
 * 计数器任务类
 * 实现Runnable接口创建线程任务
 * 
 * 涉及知识点：
 * 1. Runnable接口的实现
 * 2. 线程任务的定义方式
 * 3. 面向对象设计原则：组合优于继承
 * 4. 线程与任务的分离设计
 */
class CounterTask implements Runnable {
    private Counter counter;
    private String taskType;
    
    public CounterTask(Counter counter, String taskType) {
        this.counter = counter;
        this.taskType = taskType;
    }
    
    /**
     * 线程执行入口
     * 
     * 涉及知识点：
     * 1. Runnable接口的run()方法重写
     * 2. 线程执行逻辑的实现
     * 3. 多线程任务分发机制
     */
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            switch (taskType) {
                case "Thread-1":
                    counter.incrementSyncMethod();
                    break;
                case "Thread-2":
                    counter.incrementSyncBlock();
                    break;
                case "Thread-3":
                    Counter.incrementStaticSyncMethod();
                    break;
                default:
                    break;
            }
        }
    }
}